package nisbet.andrew.latex;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Vector;

/**
 * Represents the abstraction of a LaTeX document. This sets up a simple LaTeX article
 * and does all the boiler plate work as well as the 
 * @author anisbet
 *
 */
public class Document 
{
	private BufferedWriter writer;
	private File tempFile;
	private String origFile;
	private String author;
	private String title;
	private Vector<String>includes;
	
	public Document( String fileName, String author, String title, Vector<String> includes ) 
	{
		this.includes = includes;
		this.origFile = fileName;
		this.author   = author;
		this.title    = title;
		// create a temporary file for output
		try 
		{
			this.tempFile = File.createTempFile( this.getClass().getName(), ".temp" );
			tempFile.deleteOnExit();
			writer = new BufferedWriter( new FileWriter( tempFile ) );
		}
		catch ( IOException e )
		{
			e.printStackTrace();
		}
	}

	/**
	 * Writes the footer of the LaTeX document. Think of this as closing
	 * an open file stream - if this method isn't called it has bad implications
	 * for the document - read: it will not compile.
	 */
	public void writeFooter() 
	{
		try 
		{
			writer.write( "\\end{document}\n" );
			writer.flush();
			writer.close();
			// move the temp file to the old file name.
			File f = new File( this.origFile + ".tex" );
			
			if ( this.tempFile.renameTo( f ) )
			{
				System.out.println( "Document successfully created." );
			}
			else
			{
				System.err.println( "An error occured while trying to rename the temp file is the original file open?" );
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Writes a LaTeX header to file.
	 */
	public void writeHeader() 
	{
		try 
		{
			writer.write( "% Generated by Crawler.\n\n" );
			writer.write( "\\documentclass[12pt,letterpaper,titlepage]{report}\n" );
			for ( String include : this.includes )
			{
				writer.write( "\\usepackage{" + include + "}\n" );
			}
			writer.write( "\\usepackage{graphicx}\n" );
			writer.write( "\\usepackage{pifont}\n" );
			writer.write( "\\usepackage{textcomp}\n" );
			//writer.write( "\\usepackage{tipa}\n" ); // used for phonetic symbols
			writer.write( "\\usepackage{hyperref}\n" );
			writer.write( "\\hypersetup{\n" );
			writer.write( "colorlinks = true,\n" );
			writer.write( "linkcolor = blue,\n" );
			writer.write( "anchorcolor = blue,\n" );
			writer.write( "citecolor = red,\n" );
			writer.write( "filecolor = blue,\n" );
			//writer.write( "pagecolor = blue,\n" ); // obsolete.
			writer.write( "urlcolor = blue\n" );
			writer.write( "}\n" );
			writer.write( "\\title{" + this.title + "}\n" );
			writer.write( "\\author{" + this.author + "}\n" );
			writer.write( "\\begin{document}\n" );
			writer.write( "\\maketitle\n" );
			writer.write( "\\tableofcontents\n" );
			writer.write( "\\listoffigures\n" );
			writer.write( "\\newpage\n" );
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		}
		
	}

	/**
	 * Writes a line to the open file handle.
	 * @param line
	 */
	protected void writeLine( String line ) {
		try 
		{
			writer.write( line + "\n" );
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

	/**
	 * Document compiles itself.
	 */
	protected void compile()
	{
		// TODO check if latex is installed.
//		if ( isPdfLatexDocument )
//		{
			process( "pdflatex", this.origFile + ".tex" );
			// Done a second time to confirm links to bibref.
			process( "pdflatex", this.origFile + ".tex" );
//		}
//		else
//		{
//			process( "latex", this.origFile + ".tex" );
//			// Done a second time to confirm links to bibref.
//			process( "latex", this.origFile + ".tex" );
//			process( "dvipdf", this.origFile + ".dvi" );
//		}
		System.out.println( "done." );
	}
	
	/**
	 * @param command
	 * @param fileName
	 */
	private void process( String command, String fileName )
	{
		Process p = null;
		try 
		{
			p = Runtime.getRuntime().exec( command + " " + fileName );
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		}
		
		BufferedReader stdInput = new BufferedReader( new InputStreamReader( p.getInputStream()) );
		
		BufferedReader stdError = new BufferedReader( new InputStreamReader( p.getErrorStream() ));
		
		// read the output from the command
		String s;
		try 
		{
			while (( s = stdInput.readLine() ) != null) 
			{
			    System.out.println(s);
			}
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		}
		// read any errors from the attempted command
		
		try 
		{
			while ((s = stdError.readLine()) != null) 
			{
			    System.err.println(s);
			}
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		}
		
	}
	
}
